#include "utils/utils/date_time.h"
#include "utils/utils/date_time_format.hpp"
#include <sys/time.h>

namespace base
{
namespace utils
{
DateTime DateTime::currentDateTime()
{
    timeval time{};
    int res = gettimeofday(&time, nullptr);
    if (-1 == res)
    {
        return DateTime(std::time(nullptr), 0);
    }
    return DateTime(time.tv_sec, time.tv_usec / 1000);
}

long long DateTime::currentSecond()
{
    return std::time(nullptr);
}

DateTime::DateTime()
    : sec_(0), msec_(0)
{
}

DateTime::DateTime(const base::utils::DateTime &dateTime)
    : sec_(dateTime.sec_), msec_(dateTime.msec_)
{
}

DateTime::DateTime(std::tm *tm)
    : sec_(std::mktime(tm)), msec_(0)
{
}

DateTime::DateTime(long long int second, long long int msecond)
    : sec_(second), msec_(msecond)
{
}

DateTime::~DateTime() = default;

DateTime DateTime::addDays(int days) const
{
    DateTime dateTime(this->sec_, this->msec_);
    dateTime.sec_ += days * 24 * 60 * 60;
    return dateTime;
}
std::string DateTime::toString(const std::string &format) const
{
    return base::utils::DateTimeFormat::formatDateTime(format, sec_, msec_);
}

long long DateTime::tm2Second(tm *tm)
{
    return std::mktime(tm);;
}
DateTime DateTime::addSecond(long long int seconds) const
{
    DateTime dateTime(this->sec_, this->msec_);
    dateTime.sec_ += seconds;
    return dateTime;
}
DateTime DateTime::addMillSecond(long long int mill) const
{
    long long second = mill / 1000;
    int msecond = mill % 1000;
    DateTime dateTime(this->sec_, this->msec_);
    dateTime.sec_ += second;
    dateTime.msec_ += msecond;
    return dateTime;
}
std::tm DateTime::second2Tm(long long int second, bool *isOk/* = nullptr*/)
{
    tm tm{};
    if (localtime_r((time_t *) &second, &tm))
    {
        if (isOk) *isOk = true;
    }
    else
    {
        if (isOk) *isOk = false;
    }
    return tm;
}
long long DateTime::toSecond() const
{
    return (long long) sec_;
}
long long DateTime::toMilliSecond() const
{
    return sec_ * 1000 + msec_;
}

}
}



